package org.xfy.org.service.impl;

import cn.hutool.crypto.SecureUtil;
import org.apache.catalina.security.SecurityUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.xfy.base.util.AjaxResult;
import org.xfy.base.util.ErrorCode;
import org.xfy.base.util.JwtUtils;
import org.xfy.base.util.StrUtils;
import org.xfy.org.domain.LoginData;
import org.xfy.org.domain.Logininfo;
import org.xfy.org.domain.dto.BindDto;
import org.xfy.org.domain.dto.LoginDto;
import org.xfy.org.exception.BusinessException;
import org.xfy.org.mapper.LogininfoMapper;
import org.xfy.org.service.ILogininfoService;
import org.xfy.base.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.xfy.sys.domain.Menu;
import org.xfy.sys.domain.Permission;
import org.xfy.sys.domain.User;
import org.xfy.sys.domain.Wxuser;
import org.xfy.sys.domain.dto.EmailUserRegisterDto;
import org.xfy.sys.domain.dto.PhoneUserRegisterDto;
import org.xfy.sys.mapper.UserMapper;
import org.xfy.sys.mapper.WxuserMapper;
import org.xfy.sys.service.IMenuService;

import java.security.Security;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 业务实现类：
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private IMenuService menuService;

    @Override
    @Transactional
    public void register(PhoneUserRegisterDto registerDto, int i) {
        if (i == 1) { //前台普通用户
            Logininfo logininfo = new Logininfo();
            logininfo.setUsername(registerDto.getPhone());
            logininfo.setPhone(registerDto.getPhone());
            //生成盐值
            String salt = StrUtils.getComplexRandomString(32);
            logininfo.setSalt(salt);
            String md5 = SecureUtil.md5(salt + registerDto.getPassword());
            logininfo.setPassword(md5);
            logininfo.setDisable(true);
            logininfo.setType(i);
            logininfoMapper.add(logininfo);
            //添加User表信息
            User user = new User();
            BeanUtils.copyProperties(logininfo, user);
            user.setState(1);
            user.setLogininfoId(logininfo.getId());
            userMapper.add(user);
        }
    }

    @Override
    public void emailregister(EmailUserRegisterDto registerDto, int i) {
        if (i == 1) {
            User user = new User();
            user.setUsername(registerDto.getEmail());
            user.setEmail(registerDto.getEmail());
            String salt = StrUtils.getComplexRandomString(32);
            user.setSalt(salt);
            String md5 = SecureUtil.md5(registerDto.getPassword());
            user.setPassword(md5);
            user.setState(0);
            userMapper.add(user);
        }
    }

    @Override
    public AjaxResult login(LoginDto loginDto, Boolean b) {
        Integer type = loginDto.getType();
        //1.判断用户名存不存在
        Logininfo logininfo = logininfoMapper.findOneByusrname(loginDto);
        if (logininfo == null) {
            throw new BusinessException(ErrorCode.Besiness_SYSTEM_LOGIN_ERROR.getCode());
        }
        if (b) {
            //2.比较密码
            String password = loginDto.getPassword();
            String salt = logininfo.getSalt();
            String md5password = SecureUtil.md5(salt + password);
            if (!logininfo.getPassword().equals(md5password)) {
                throw new BusinessException(ErrorCode.Besiness_SYSTEM_LOGIN_ERROR.getCode());
            }
        }
        //将当前登录人的信息放到logindata里面
        LoginData loginData = new LoginData();
        loginData.setLogininfo(logininfo);
        String token = JwtUtils.getCode(loginData, 24 * 60 * 60 * 7);
        Map<String, Object> map = new HashMap<>();
        if(loginDto.getType()==1){
            map.put("token", token);
            logininfo.setSalt(null);
            logininfo.setPassword(null);
            map.put("user", logininfo);
            return AjaxResult.me().setResultObj(map);
        }
        //menus进行数据处理 处理成一颗树
        List<Menu> menuList = logininfoMapper.findMuesBylogininfoId(logininfo.getId());
        List<Long> collect = menuList.stream().map(Menu::getParentId).distinct().collect(Collectors.toList());
        List<Menu> top=menuService.findMenusByPIds(collect);
        top.addAll(menuList);
        List<Menu> menus = menuService.menusTree(top);

        loginData.setMenus(menus);
        List<String> permissions=logininfoMapper.findPermissionBylogininfoId(logininfo.getId());
        loginData.setPermissions(permissions);
        //4.返回给前端保存
        //3.获取token
        map.put("token", token);
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("user", logininfo);
        map.put("menus", menus);
        map.put("permission", permissions);
        return AjaxResult.me().setResultObj(map);
    }

    @Override
    public AjaxResult bind(BindDto bindDto) {
        Logininfo logininfo = logininfoMapper.findOneByname(bindDto.getUsername());
        if (logininfo == null) {
            AjaxResult.me().setSuccess(false).setMessage("用户位注册");
        }
        //2.比较密码
        String password = bindDto.getPassword();
        String salt = logininfo.getSalt();
        String md5password = SecureUtil.md5(salt + password);
        if (!logininfo.getPassword().equals(md5password)) {
            throw new BusinessException(ErrorCode.Besiness_SYSTEM_LOGIN_ERROR.getCode());
        }
        Wxuser wxuser = wxuserMapper.finOneByopenid(bindDto.getOpenId());
        User user = userMapper.findOneByLogininfo(logininfo.getId());
        if (wxuser != null) {
            wxuser.setUserId(user.getId());
            wxuserMapper.update(wxuser);
        }
        LoginDto loginDto = new LoginDto();
        loginDto.setType(1);
        loginDto.setUsername(logininfo.getUsername());
        logininfo.setPassword(logininfo.getPassword());
        return login(loginDto, false);
    }
}
